home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power CD-ROM!! 8
/
Power CD-ROM 8.iso
/
prgmming
/
pmd110
/
bbobject.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-11-13
|
8KB
|
377 lines
{ Created : 1994-06-23 (c) Copyright 1994 by Berend de Boer
Unit to facilitate ports of Dos/DPMI objects to Windows. The object created here
initializes all fields to zero, just as the Dos TObject.
And it implements TResourceFile which was for some reason(??) missing in
the windows version of Objects
Last changes :
}
{$IFDEF DPMI}
{$X+,S-}
{$ELSE}
{$X+,F+,O+}
{$ENDIF}
unit BBObject;
interface
{$IFDEF Windows}
uses Objects;
type
TObject = object(Objects.TObject)
constructor Init;
end;
{ Private resource manager types }
const
RStreamMagic: Longint = $52504246; { 'FBPR' }
RStreamBackLink: Longint = $4C424246; { 'FBBL' }
type
PResourceItem = ^TResourceItem;
TResourceItem = record
Pos: Longint;
Size: Longint;
Key: String;
end;
{ TResourceCollection object }
PResourceCollection = ^TResourceCollection;
TResourceCollection = object(TStringCollection)
procedure FreeItem(Item: Pointer); virtual;
function GetItem(var S: TStream): Pointer; virtual;
function KeyOf(Item: Pointer): Pointer; virtual;
procedure PutItem(var S: TStream; Item: Pointer); virtual;
end;
{ TResourceFile object }
PResourceFile = ^TResourceFile;
TResourceFile = object(TObject)
Stream: PStream;
Modified: Boolean;
constructor Init(AStream: PStream);
destructor Done; virtual;
function Count: Integer;
procedure Delete(Key: String);
procedure Flush;
function Get(Key: String): PObject;
function KeyAt(I: Integer): String;
procedure Put(Item: PObject; Key: String);
function SwitchTo(AStream: PStream; Pack: Boolean): PStream;
private
BasePos: Longint;
IndexPos: Longint;
Index: TResourceCollection;
end;
{$ENDIF}
implementation
{$IFDEF Windows}
constructor TObject.Init;
type
Image = record
Link: Word;
Data: record end;
end;
begin
FillChar(Image(Self).Data, SizeOf(Self) - SizeOf(TObject), 0);
inherited Init;
end;
{ TResourceCollection }
procedure TResourceCollection.FreeItem(Item: Pointer);
begin
FreeMem(Item, Length(PResourceItem(Item)^.Key) +
(SizeOf(TResourceItem) - SizeOf(String) + 1));
end;
function TResourceCollection.GetItem(var S: TStream): Pointer;
var
Pos: Longint;
Size: Longint;
L: Byte;
P: PResourceItem;
begin
S.Read(Pos, SizeOf(Longint));
S.Read(Size, SizeOf(Longint));
S.Read(L, 1);
GetMem(P, L + (SizeOf(TResourceItem) - SizeOf(String) + 1));
P^.Pos := Pos;
P^.Size := Size;
P^.Key[0] := Char(L);
S.Read(P^.Key[1], L);
GetItem := P;
end;
function TResourceCollection.KeyOf(Item: Pointer): Pointer; assembler;
asm
MOV AX,Item.Word[0]
MOV DX,Item.Word[2]
ADD AX,OFFSET TResourceItem.Key
end;
procedure TResourceCollection.PutItem(var S: TStream; Item: Pointer);
begin
S.Write(PResourceItem(Item)^, Length(PResourceItem(Item)^.Key) +
(SizeOf(TResourceItem) - SizeOf(String) + 1));
end;
{ TResourceFile }
constructor TResourceFile.Init(AStream: PStream);
type
{$IFDEF NewExeFormat}
TExeHeader = record
eHdrSize: Word;
eMinAbove: Word;
eMaxAbove: Word;
eInitSS: Word;
eInitSP: Word;
eCheckSum: Word;
eInitPC: Word;
eInitCS: Word;
eRelocOfs: Word;
eOvlyNum: Word;
eRelocTab: Word;
eSpace: Array[1..30] of Byte;
eNewHeader: Word;
end;
{$ENDIF}
THeader = record
Signature: Word;
case Integer of
0: (
LastCount: Word;
PageCount: Word;
ReloCount: Word);
1: (
InfoType: Word;
InfoSize: Longint);
end;
var
Found, Stop: Boolean;
Header: THeader;
{$IFDEF NewExeFormat}
ExeHeader: TExeHeader;
{$ENDIF}
begin
TObject.Init;
Stream := AStream;
BasePos := Stream^.GetPos;
Found := False;
repeat
Stop := True;
if BasePos <= Stream^.GetSize - SizeOf(THeader) then
begin
Stream^.Seek(BasePos);
Stream^.Read(Header, SizeOf(THeader));
case Header.Signature of
{$IFDEF NewExeFormat}
$5A4D:
begin
Stream^.Read(ExeHeader, SizeOf(TExeHeader));
BasePos := ExeHeader.eNewHeader;
Stop := False;
end;
$454E:
begin
BasePos := Stream^.GetSize - 8;
Stop := False;
end;
$4246:
begin
Stop := False;
case Header.Infotype of
$5250: {Found Resource}
begin
Found := True;
Stop := True;
end;
$4C42: Dec(BasePos, Header.InfoSize - 8); {Found BackLink}
$4648: Dec(BasePos, SizeOf(THeader) * 2); {Found HelpFile}
else
Stop := True;
end;
end;
$424E:
if Header.InfoType = $3230 then {Found Debug Info}
begin
Dec(BasePos, Header.InfoSize);
Stop := False;
end;
{$ELSE}
$5A4D:
begin
Inc(BasePos, LongMul(Header.PageCount, 512) -
(-Header.LastCount and 511));
Stop := False;
end;
$4246:
if Header.InfoType = $5250 then Found := True else
begin
Inc(BasePos, Header.InfoSize + 8);
Stop := False;
end;
{$ENDIF}
end;
end;
until Stop;
if Found then
begin
Stream^.Seek(BasePos + SizeOf(Longint) * 2);
Stream^.Read(IndexPos, SizeOf(Longint));
Stream^.Seek(BasePos + IndexPos);
Index.Load(Stream^);
end else
begin
IndexPos := SizeOf(Longint) * 3;
Index.Init(0, 8);
end;
end;
destructor TResourceFile.Done;
begin
Flush;
Index.Done;
Dispose(Stream, Done);
end;
function TResourceFile.Count: Integer;
begin
Count := Index.Count;
end;
procedure TResourceFile.Delete(Key: String);
var
I: Integer;
begin
if Index.Search(@Key, I) then
begin
Index.Free(Index.At(I));
Modified := True;
end;
end;
procedure TResourceFile.Flush;
var
ResSize: Longint;
LinkSize: Longint;
begin
if Modified then
begin
Stream^.Seek(BasePos + IndexPos);
Index.Store(Stream^);
ResSize := Stream^.GetPos - BasePos;
LinkSize := ResSize + SizeOf(Longint) * 2;
Stream^.Write(RStreamBackLink, SizeOf(Longint));
Stream^.Write(LinkSize, SizeOf(Longint));
Stream^.Seek(BasePos);
Stream^.Write(RStreamMagic, SizeOf(Longint));
Stream^.Write(ResSize, SizeOf(Longint));
Stream^.Write(IndexPos, SizeOf(Longint));
Stream^.Flush;
Modified := False;
end;
end;
function TResourceFile.Get(Key: String): PObject;
var
I: Integer;
begin
if not Index.Search(@Key, I) then Get := nil else
begin
Stream^.Seek(BasePos + PResourceItem(Index.At(I))^.Pos);
Get := Stream^.Get;
end;
end;
function TResourceFile.KeyAt(I: Integer): String;
begin
KeyAt := PResourceItem(Index.At(I))^.Key;
end;
procedure TResourceFile.Put(Item: PObject; Key: String);
var
I: Integer;
P: PResourceItem;
begin
if Index.Search(@Key, I) then P := Index.At(I) else
begin
GetMem(P, Length(Key) + (SizeOf(TResourceItem) - SizeOf(String) + 1));
P^.Key := Key;
Index.AtInsert(I, P);
end;
P^.Pos := IndexPos;
Stream^.Seek(BasePos + IndexPos);
Stream^.Put(Item);
IndexPos := Stream^.GetPos - BasePos;
P^.Size := IndexPos - P^.Pos;
Modified := True;
end;
function TResourceFile.SwitchTo(AStream: PStream; Pack: Boolean): PStream;
var
NewBasePos: Longint;
procedure DoCopyResource(Item: PResourceItem); far;
begin
Stream^.Seek(BasePos + Item^.Pos);
Item^.Pos := AStream^.GetPos - NewBasePos;
AStream^.CopyFrom(Stream^, Item^.Size);
end;
begin
SwitchTo := Stream;
NewBasePos := AStream^.GetPos;
if Pack then
begin
AStream^.Seek(NewBasePos + SizeOf(Longint) * 3);
Index.ForEach(@DoCopyResource);
IndexPos := AStream^.GetPos - NewBasePos;
end else
begin
Stream^.Seek(BasePos);
AStream^.CopyFrom(Stream^, IndexPos);
end;
Stream := AStream;
Modified := True;
BasePos := NewBasePos;
end;
{$ENDIF}
end. { of unit BBOject }